using System;
using System.Collections.Generic;
using System.Text;
using Forecast.Database;
using NUnit.Framework;

namespace Forecast.Business.Test
{
    [TestFixture]
    public class TestAcceptOffer
    {
        #region Variables

        private AcceptOffer _acceptOffer;
        private Player _buyer;
        private Player _seller;
        private Prediction _prediction;
        private Holding _buyerHolding;
        private Holding _sellerHolding;
        private Offer _buyOffer;
        private Offer _sellOffer;

        #endregion
        #region Setup / Teardown

        [SetUp]
        public void Init()
        {
            _acceptOffer = new AcceptOffer();
            _buyer = Mocks.GetBuyer();
            _seller = Mocks.GetSeller();
            _prediction = Mocks.GetPrediction();
            _buyerHolding = Mocks.GetBuyerHolding();
            _sellerHolding = Mocks.GetSellerHolding();
            _buyOffer = Mocks.GetBuyOffer();
            _sellOffer = Mocks.GetSellOffer();
        }

        #endregion
        #region Tests for Buy

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void BuyNullBuyer()
        {
            _acceptOffer.Buy(null, _seller, _buyerHolding, _sellerHolding,_prediction, _buyOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void BuyNullSeller()
        {
            _acceptOffer.Buy(_buyer, null, _buyerHolding, _sellerHolding, _prediction, _buyOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void BuyNullBuyerHolding()
        {
            _acceptOffer.Buy(_buyer, _seller, null, _sellerHolding, _prediction, _buyOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void BuyNullSellerHolding()
        {
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, null, _prediction, _buyOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void BuyNullPredition()
        {
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, null, _buyOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void BuyNullOffer()
        {
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, null, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyPredictionClosed()
        {
            _prediction.IsClosed = true;
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, _buyOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyPredictionNotActive()
        {
            _prediction.IsActive = false;
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, _buyOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyPredictionEndDateExpired()
        {
            _prediction.EndDate = DateTime.Today.AddDays(-1);
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, _buyOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyOfferEndDateExpired()
        {
            _buyOffer.EndDate = DateTime.Today.AddDays(-1);
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, _buyOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyOfferInactive()
        {
            _buyOffer.IsActive = false;
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, _buyOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyBuyerDoNotOwnHolding()
        {
            _buyer.Id = -1;
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, _buyOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuySellerDoNotOwnHolding()
        {
            _seller.Id = -1;
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, _buyOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyBuyerHoldingIsOfAnotherPrediction()
        {
            _buyerHolding.PredictionId = -1;
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, _buyOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuySellerHoldingIsOfAnotherPrediction()
        {
            _sellerHolding.PredictionId = -1;
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, _buyOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyOfferIsOfAnotherPrediction()
        {
            _buyOffer.PredictionId = -1;
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, _buyOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyOfferDoesNotBelongToBuyer()
        {
            _buyer.Id = -1;
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, _buyOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyBuyerAndSellerAreTheSame()
        {
            _seller.Id = _buyer.Id;
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, _buyOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyTooManyPredictions()
        {
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, _sellOffer, 1000, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyTooFewPredictions()
        {
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, _buyOffer, 0, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyTryingToBuyOwnStock()
        {
            _seller.Id = _buyer.Id;
            _sellerHolding.PlayerId = _seller.Id;
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, _buyOffer, 1, 0);
        }

        [Test]
        public void BuyFullAcceptedOffer()
        {
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, _buyOffer, _buyOffer.NumPredictions, 0);
            Assert.AreEqual(1500, _acceptOffer.AcceptOfferBuyer.Cash);
            Assert.AreEqual(20, _acceptOffer.AcceptOfferBuyerHolding.NumPredictions);
            Assert.AreNotEqual(null, _acceptOffer.AcceptOfferNewsItemBuyer);
            //Assert.AreNotEqual(null, _acceptOffer.AcceptOfferNewsItemSeller);
            Assert.AreEqual(MockIds.SELLER, _acceptOffer.AcceptOfferOffer.AcceptorId);
            Assert.AreEqual(DateTime.Today.AddDays(2), _acceptOffer.AcceptOfferOffer.EndDate);
            Assert.AreEqual(true, _acceptOffer.AcceptOfferOffer.IsAccepted);
            Assert.AreEqual(false, _acceptOffer.AcceptOfferOffer.IsActive);
            Assert.AreEqual(true, _acceptOffer.AcceptOfferOffer.IsBuy);
            Assert.AreEqual(10, _acceptOffer.AcceptOfferOffer.NumPredictions);
            Assert.AreEqual(MockIds.BUYER, _acceptOffer.AcceptOfferOffer.PlayerId);
            Assert.AreEqual(MockIds.PREDICTION, _acceptOffer.AcceptOfferOffer.PredictionId);
            Assert.AreEqual(60, _acceptOffer.AcceptOfferOffer.Price);
            Assert.AreEqual(20, _acceptOffer.AcceptOfferPrediction.LastChange);
            Assert.AreEqual(60, _acceptOffer.AcceptOfferPrediction.LastValue);
            Assert.AreEqual(2100, _acceptOffer.AcceptOfferSeller.Cash);
            Assert.AreEqual(65, _acceptOffer.AcceptOfferSellerHolding.NumPredictions);
            Assert.AreEqual(null, _acceptOffer.AcceptOfferSubOffer);
        }

        public void BuyPartialAcceptedOffer()
        {
            _acceptOffer.Buy(_buyer, _seller, _buyerHolding, _sellerHolding, _prediction, _buyOffer, 5, 0);
            Assert.AreEqual(_acceptOffer.AcceptOfferBuyer.Cash, 500);
            Assert.AreEqual(_acceptOffer.AcceptOfferBuyerHolding.NumPredictions, 55);
            Assert.AreEqual(_acceptOffer.AcceptOfferSellerHolding.NumPredictions, 45);
            Assert.AreNotEqual(_acceptOffer.AcceptOfferNewsItemBuyer, null);
            //Assert.AreNotEqual(_acceptOffer.AcceptOfferNewsItemSeller, null);
            Assert.AreEqual(_acceptOffer.AcceptOfferOffer.AcceptorId, _seller.Id);
            Assert.AreEqual(_acceptOffer.AcceptOfferOffer.EndDate, _buyOffer.EndDate);
            Assert.AreEqual(_acceptOffer.AcceptOfferOffer.IsAccepted, true);
            Assert.AreEqual(_acceptOffer.AcceptOfferOffer.IsActive, false);
            Assert.AreEqual(_acceptOffer.AcceptOfferOffer.IsBuy, true);
            Assert.AreEqual(_acceptOffer.AcceptOfferOffer.NumPredictions, 5);
            Assert.AreEqual(_acceptOffer.AcceptOfferOffer.PlayerId, _buyer.Id);
            Assert.AreEqual(_acceptOffer.AcceptOfferOffer.PredictionId, _prediction.Id);
            Assert.AreEqual(_acceptOffer.AcceptOfferOffer.Price, 60);
            Assert.AreEqual(_acceptOffer.AcceptOfferPrediction.LastChange, 20);
            Assert.AreEqual(_acceptOffer.AcceptOfferPrediction.LastValue, 60);
            Assert.AreEqual(_acceptOffer.AcceptOfferSeller.Cash, 2800);
            Assert.AreEqual(_acceptOffer.AcceptOfferSubOffer.AcceptorId, 0);
            Assert.AreEqual(_acceptOffer.AcceptOfferSubOffer.EndDate, _acceptOffer.AcceptOfferOffer.EndDate);
            Assert.AreEqual(_acceptOffer.AcceptOfferSubOffer.IsAccepted, false);
            Assert.AreEqual(_acceptOffer.AcceptOfferSubOffer.IsActive, true);
            Assert.AreEqual(_acceptOffer.AcceptOfferSubOffer.IsBuy, true);
            Assert.AreEqual(_acceptOffer.AcceptOfferSubOffer.NumPredictions, 5);
            Assert.AreEqual(_acceptOffer.AcceptOfferSubOffer.PlayerId, _buyer.Id);
            Assert.AreEqual(_acceptOffer.AcceptOfferSubOffer.PredictionId, _prediction.Id);
            Assert.AreEqual(_acceptOffer.AcceptOfferSubOffer.Price, 60);
        }

        #endregion
        #region Tests for Sell

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void SellNullBuyer()
        {
            _acceptOffer.Sell(null, _seller, _buyerHolding, _prediction, _sellOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void SellNullSeller()
        {
            _acceptOffer.Sell(_buyer, null, _buyerHolding, _prediction, _sellOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void SellNullBuyerHolding()
        {
            _acceptOffer.Sell(_buyer, _seller, null, _prediction, _sellOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void SellNullPredition()
        {
            _acceptOffer.Sell(_buyer, _seller, _buyerHolding, null, _sellOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void SellNullOffer()
        {
            _acceptOffer.Sell(_buyer, _seller, _buyerHolding, _prediction, null, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellBuyerNotEnoughCash()
        {
            _buyer.Cash = 0;
            _acceptOffer.Sell(_buyer, _seller, _buyerHolding, _prediction, _sellOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellPredictionClosed()
        {
            _prediction.IsClosed = true;
            _acceptOffer.Sell(_buyer, _seller, _buyerHolding, _prediction, _sellOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellPredictionNotActive()
        {
            _prediction.IsActive = false;
            _acceptOffer.Sell(_buyer, _seller, _buyerHolding, _prediction, _sellOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellPredictionEndDateExpired()
        {
            _prediction.EndDate = DateTime.Today.AddDays(-1);
            _acceptOffer.Sell(_buyer, _seller, _buyerHolding, _prediction, _sellOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellOfferEndDateExpired()
        {
            _sellOffer.EndDate = DateTime.Today.AddDays(-1);
            _acceptOffer.Sell(_buyer, _seller, _buyerHolding, _prediction, _sellOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellOfferInactive()
        {
            _sellOffer.IsActive = false;
            _acceptOffer.Sell(_buyer, _seller, _buyerHolding, _prediction, _sellOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellHoldingIsOfAnotherPrediction()
        {
            _buyerHolding.PredictionId = -1;
            _acceptOffer.Sell(_buyer, _seller, _buyerHolding, _prediction, _sellOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellOfferIsOfAnotherPrediction()
        {
            _sellOffer.PredictionId = -1;
            _acceptOffer.Sell(_buyer, _seller, _buyerHolding, _prediction, _sellOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellOfferDoesNotBelongToSeller()
        {
            _seller.Id = -1;
            _acceptOffer.Sell(_buyer, _seller, _buyerHolding, _prediction, _sellOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellBuyerAndSellerAreTheSame()
        {
            _seller.Id = _buyer.Id;
            _acceptOffer.Sell(_buyer, _seller, _buyerHolding, _prediction, _sellOffer, 10, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellTooManyPredictions()
        {
            _acceptOffer.Sell(_buyer, _seller, _buyerHolding, _prediction, _sellOffer, 1000, 0);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellTooFewPredictions()
        {
            _acceptOffer.Sell(_buyer, _seller, _buyerHolding, _prediction, _sellOffer, 0, 0);
        }

        [Test]
        public void SellBuyerDoNotOwnHolding()
        {
            _buyerHolding.NumPredictions = 0;
            _acceptOffer.Sell(_buyer, _seller, _buyerHolding, _prediction, _sellOffer, _sellOffer.NumPredictions, 0);
            Assert.AreEqual(615, _acceptOffer.AcceptOfferBuyer.Cash);
            Assert.AreEqual(15, _acceptOffer.AcceptOfferBuyerHolding.NumPredictions);
            Assert.AreNotEqual(null, _acceptOffer.AcceptOfferNewsItemBuyer);
            //Assert.AreNotEqual(null, _acceptOffer.AcceptOfferNewsItemSeller);
            Assert.AreEqual(MockIds.BUYER, _acceptOffer.AcceptOfferOffer.AcceptorId);
            Assert.AreEqual(DateTime.Today.AddDays(4), _acceptOffer.AcceptOfferOffer.EndDate);
            Assert.AreEqual(true, _acceptOffer.AcceptOfferOffer.IsAccepted);
            Assert.AreEqual(false, _acceptOffer.AcceptOfferOffer.IsActive);
            Assert.AreEqual(false, _acceptOffer.AcceptOfferOffer.IsBuy);
            Assert.AreEqual(15, _acceptOffer.AcceptOfferOffer.NumPredictions);
            Assert.AreEqual(MockIds.SELLER, _acceptOffer.AcceptOfferOffer.PlayerId);
            Assert.AreEqual(MockIds.PREDICTION, _acceptOffer.AcceptOfferOffer.PredictionId);
            Assert.AreEqual(59, _acceptOffer.AcceptOfferOffer.Price);
            Assert.AreEqual(18, _acceptOffer.AcceptOfferPrediction.LastChange);
            Assert.AreEqual(59, _acceptOffer.AcceptOfferPrediction.LastValue);
            Assert.AreEqual(2385, _acceptOffer.AcceptOfferSeller.Cash);
            Assert.AreEqual(null, _acceptOffer.AcceptOfferSubOffer);
        }

        [Test]
        public void SellFullAcceptedOffer()
        {
            _acceptOffer.Sell(_buyer, _seller, _buyerHolding, _prediction, _sellOffer, _sellOffer.NumPredictions, 0);
            Assert.AreEqual(615, _acceptOffer.AcceptOfferBuyer.Cash);
            Assert.AreEqual(25, _acceptOffer.AcceptOfferBuyerHolding.NumPredictions);
            Assert.AreNotEqual(null, _acceptOffer.AcceptOfferNewsItemBuyer);
            //Assert.AreNotEqual(null, _acceptOffer.AcceptOfferNewsItemSeller);
            Assert.AreEqual(MockIds.BUYER, _acceptOffer.AcceptOfferOffer.AcceptorId);
            Assert.AreEqual(DateTime.Today.AddDays(4), _acceptOffer.AcceptOfferOffer.EndDate);
            Assert.AreEqual(true, _acceptOffer.AcceptOfferOffer.IsAccepted);
            Assert.AreEqual(false, _acceptOffer.AcceptOfferOffer.IsActive);
            Assert.AreEqual(false, _acceptOffer.AcceptOfferOffer.IsBuy);
            Assert.AreEqual(15, _acceptOffer.AcceptOfferOffer.NumPredictions);
            Assert.AreEqual(MockIds.SELLER, _acceptOffer.AcceptOfferOffer.PlayerId);
            Assert.AreEqual(MockIds.PREDICTION, _acceptOffer.AcceptOfferOffer.PredictionId);
            Assert.AreEqual(59, _acceptOffer.AcceptOfferOffer.Price);
            Assert.AreEqual(18, _acceptOffer.AcceptOfferPrediction.LastChange);
            Assert.AreEqual(59, _acceptOffer.AcceptOfferPrediction.LastValue);
            Assert.AreEqual(2385, _acceptOffer.AcceptOfferSeller.Cash);
            Assert.AreEqual(null, _acceptOffer.AcceptOfferSubOffer);
        }

        [Test]
        public void SellPartialAcceptedOffer()
        {
            _acceptOffer.Sell(_buyer, _seller, _buyerHolding, _prediction, _sellOffer, 5, 0);
            Assert.AreEqual(1205, _acceptOffer.AcceptOfferBuyer.Cash);
            Assert.AreEqual(15, _acceptOffer.AcceptOfferBuyerHolding.NumPredictions);
            Assert.AreNotEqual(null, _acceptOffer.AcceptOfferNewsItemBuyer);
            //Assert.AreNotEqual(null, _acceptOffer.AcceptOfferNewsItemSeller);
            Assert.AreEqual(MockIds.BUYER, _acceptOffer.AcceptOfferOffer.AcceptorId);
            Assert.AreEqual(DateTime.Today.AddDays(4), _acceptOffer.AcceptOfferOffer.EndDate);
            Assert.AreEqual(true, _acceptOffer.AcceptOfferOffer.IsAccepted);
            Assert.AreEqual(false, _acceptOffer.AcceptOfferOffer.IsActive);
            Assert.AreEqual(false, _acceptOffer.AcceptOfferOffer.IsBuy);
            Assert.AreEqual(5, _acceptOffer.AcceptOfferOffer.NumPredictions);
            Assert.AreEqual(MockIds.SELLER, _acceptOffer.AcceptOfferOffer.PlayerId);
            Assert.AreEqual(MockIds.PREDICTION, _acceptOffer.AcceptOfferOffer.PredictionId);
            Assert.AreEqual(59, _acceptOffer.AcceptOfferOffer.Price);
            Assert.AreEqual(18, _acceptOffer.AcceptOfferPrediction.LastChange);
            Assert.AreEqual(59, _acceptOffer.AcceptOfferPrediction.LastValue);
            Assert.AreEqual(1795, _acceptOffer.AcceptOfferSeller.Cash);
            Assert.AreEqual(0, _acceptOffer.AcceptOfferSubOffer.AcceptorId);
            Assert.AreEqual(DateTime.Today.AddDays(4), _acceptOffer.AcceptOfferSubOffer.EndDate);
            Assert.AreEqual(false, _acceptOffer.AcceptOfferSubOffer.IsAccepted);
            Assert.AreEqual(true, _acceptOffer.AcceptOfferSubOffer.IsActive);
            Assert.AreEqual(false, _acceptOffer.AcceptOfferSubOffer.IsBuy);
            Assert.AreEqual(10, _acceptOffer.AcceptOfferSubOffer.NumPredictions);
            Assert.AreEqual(MockIds.SELLER, _acceptOffer.AcceptOfferSubOffer.PlayerId);
            Assert.AreEqual(MockIds.PREDICTION, _acceptOffer.AcceptOfferSubOffer.PredictionId);
            Assert.AreEqual(59, _acceptOffer.AcceptOfferSubOffer.Price);
        }

        #endregion
    }
}
